/**
 * Copyright 2011 Google
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.appengine.codelab;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;

/**
 * This class defines the methods for basic operations of create, update & retrieve
 * for estabelecimento entity
 * 
 * @author 
 *
 */
public class Estabelecimento {

	/**
	 * Checks if the entity is existing and if it is not, it creates the entity
	 * else it updates the entity
	 * 
	 * @param estabelecimento_tipo
	 *          : tipo of the Estabelecimento
	 * @param estabelecimento_nome
	 *          : nome of the Estabelecimento
	
	 */
  public static void createOrUpdateEstabelecimento(String estabelecimento_id, String estabelecimento_tipo, String estabelecimento_nome, String localidade_id) {
	  Entity estabelecimento = getSingleEstabelecimento(estabelecimento_id);
	  Entity localidade = Localidade.getSingleLocalidade(localidade_id);
    if (estabelecimento == null) {
    	estabelecimento = new Entity("Estabelecimento", estabelecimento_id);
    	estabelecimento.setProperty("estabelecimento_id", estabelecimento_id);
    	estabelecimento.setProperty("estabelecimento_tipo", estabelecimento_tipo);
    	estabelecimento.setProperty("estabelecimento_nome", estabelecimento_nome);
    	estabelecimento.setProperty("localidade_id", localidade.getProperty("localidade_id").toString());
    
    } else {
      if (estabelecimento_tipo != null && !"".equals(estabelecimento_tipo)) {
    	  estabelecimento.setProperty("estabelecimento_tipo", estabelecimento_tipo);
      }
      if (estabelecimento_nome != null && !"".equals(estabelecimento_nome)) {
    	  estabelecimento.setProperty("estabelecimento_nome", estabelecimento_nome);
      }
     
    }
    Util.persistEntity(estabelecimento);
  }

	/**
	 * List all the estabelecimento available
	 * 
	 * @return an iterable list with all the estabelecimentos
	 */
  public static Iterable<Entity> getAllEstabelecimento() {
    Iterable<Entity> entities = Util.listEntities("Estabelecimento", null, null);
    return entities;
  }

	/**
	 * Searches for a Estabelecimento and returns the entity as an iterable The search is
	 * performed by creating a query and searching for the attribute
	 * 
	 * @param estabelecimento_nome
	 *          : nome of the Estabelecimento
	 * @return iterable with the Estabelecimento searched for
	 */
  public static Iterable<Entity> getEstabelecimento(String estabelecimento_id) {
    Iterable<Entity> entities = Util.listEntities("Estabelecimento", "estabelecimento_id", estabelecimento_id);
    return entities;
  }
  
  public static Iterable<Entity> getEstabelecimentoForLocalidade(String kind, String localidade_id) {
	    Key ancestorKey = KeyFactory.createKey("Localidade", localidade_id);
	    return Util.listChildren("Estabelecimento", ancestorKey);
  }

	/**
	 * Searches for a Estabelecimento and returns the entity as an iterable The search is
	 * key based instead of query
	 * 
	 * @param estabelecimento_id
	 *          : id of the Estabelecimento
	 * @return the entity with the Estabelecimento as key
	 */
  public static Entity getSingleEstabelecimento(String estabelecimento_id) {
	    Iterable<Entity> results = Util.listEntities("Estabelecimento", "estabelecimento_id", estabelecimento_id);
	    List<Entity> entity = new ArrayList<Entity>();
	    for(Entity e : results)
	      if(e!=null)
	        entity.add(e);
	      if (!entity.isEmpty()) {
	        return (Entity)entity.remove(0);
	      }
		  return null;
	  }

	public static Collection<ItemRelatorioEstabelecimentosSuspeitos> getAllEstabelecimentosSuspeitos(Date dataIncial,	Date dataFinal, String pais, String estado,	String cidade) 
	{
		DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
		Map<String, ItemRelatorioEstabelecimentosSuspeitos> itens = new HashMap<String, ItemRelatorioEstabelecimentosSuspeitos>();
		
		Query query = new Query("Transacao");
		query.addFilter("trans_data", FilterOperator.GREATER_THAN_OR_EQUAL, Common.dateToInt(dataIncial).toString());
		query.addFilter("trans_data", FilterOperator.LESS_THAN_OR_EQUAL, Common.dateToInt(dataFinal).toString());
		
		Iterable<Entity> transacoes = datastoreService.prepare(query).asIterable();
		
		for( Entity transacao : transacoes )
		{
			String idEstabelecimento = (String) transacao.getProperty("estabelecimento_id");
			Entity estabelecimento = getEstabelecimento(idEstabelecimento).iterator().next();
			
			Entity localidade = Localidade.getSingleLocalidade((String) estabelecimento.getProperty("localidade_id"));
			
			if( pais != null && ! pais.isEmpty() && ! pais.equals(localidade.getProperty("localidade_country"))){
				continue;
			}

			if( estado != null && ! estado.isEmpty() && ! estado.equals(localidade.getProperty("localidade_state"))){
				continue;
			}

			if( cidade != null && ! cidade.isEmpty() && ! cidade.equals(localidade.getProperty("localidade_city"))){
				continue;
			}

			Iterable<Entity> fraudes = Util.listEntities("Fraude", "trans_id", transacao.getProperty("trans_id").toString());
			
			if( ! fraudes.iterator().hasNext() ){
				continue;
			}
			
			if( itens.containsKey(idEstabelecimento) ){
				itens.get(idEstabelecimento).addValorFraudulento( (Double) transacao.getProperty("trans_price") );
			}
			else {
				ItemRelatorioEstabelecimentosSuspeitos item = new ItemRelatorioEstabelecimentosSuspeitos();
				item.setCidade((String) localidade.getProperty("localidade_city"));
				item.setUf((String) localidade.getProperty("localidade_state"));
				item.setPais((String) localidade.getProperty("localidade_country"));
				item.setNome((String) estabelecimento.getProperty("estabelecimento_nome"));
				item.setCodigo(idEstabelecimento);
				item.setValorFraudulento((Double) transacao.getProperty("trans_price"));
				
				itens.put(idEstabelecimento, item);
			}
		}
		
		return itens.values();
	}
}
